package org.awa.demo.opencv.demo;

import lombok.extern.slf4j.Slf4j;
import org.awa.demo.opencv.bean.Rgb;
import org.awa.demo.opencv.bean.RgbRange;
import org.awa.demo.opencv.gis.bean.Element;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.osgi.OpenCVNativeLoader;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author mijiupro
 */
@Slf4j
public class FaceDetection {

    //人脸检测器
    private static final CascadeClassifier FACE_DETECTOR;

    //人脸模型xml文件路径
    private static final String FACE_MODEL_PATH = "src/main/opencv/model/haarcascade_frontalface_alt.xml";
    //测试图片文件夹路径
    private static final String TRAINING_DATA_DIR = "src/main/opencv/input";
    //检测并处理后保存图片路径
    private static final String DETECTION_RESULT ="src/main/opencv/output";

    public static final String FILE_UPLOAD_PREF = "D://soundDemo/";
    public static final String FILE_UPLOAD_URL_PREF = "http://192.168.0.50:9865/gis/sound/png?path=";
    public static final String GEOJSON_PATH = "D://soundDemo/demoGeoJson.json";
    public static final String GEOJSON_PATH_SINGLE = "D://soundDemo/demoGeoJson_signle.json";



    static {
        System.load("D:\\workspace\\open-cv\\open-cv\\src\\main\\resources\\libs\\opencv_java481.dll");
//        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        FACE_DETECTOR = new CascadeClassifier(FACE_MODEL_PATH);//创建级联分类器加载人脸模型xml文件
    }

    public static Mat createMat(byte[] bb){
        Mat image = Imgcodecs.imdecode(new MatOfByte(bb), Imgcodecs.IMREAD_UNCHANGED);
        return image;
    }

    /**
     * 测试模型
     */
    public static int testModel(Mat image,String outFileName) {
        // 加载样本图片
//        Mat image = Imgcodecs.imread(TRAINING_DATA_DIR+"/tangdun.jpg");
        // 检测人脸
        MatOfRect faceDetections = new MatOfRect();
        FACE_DETECTOR.detectMultiScale(image, faceDetections);

        int numFaces = faceDetections.toArray().length;
        System.out.println("人脸数量: " + numFaces);
        // 绘制标人脸识框并打印人脸位置坐标
        Arrays.stream(faceDetections.toArray()).forEach(
                (rect) -> {
                    Imgproc.rectangle(image, new Point(rect.x, rect.y),
                            new Point(rect.x + rect.width, rect.y + rect.height),
                            new Scalar(0, 255, 0));
                    System.out.println("坐标： (" + rect.x + ", " + rect.y + ")");
                });

        // 保存处理后的图片
        Imgcodecs.imwrite(DETECTION_RESULT + "/" + outFileName, image);
        return numFaces;
    }

    public static void main(String[] args) {
//        Mat image = Imgcodecs.imread(TRAINING_DATA_DIR+"/tangdun.jpg");
//        testModel(image,"tangdun_face.jpg");
        int xLength = 256;
        int yLength = 256;

        createMat("D://demoTest1.png",xLength,yLength,254d,0d,0d);
        createMat("D://demoTest2.png",xLength,yLength,0d,254d,0d);
        createMat("D://demoTest3.png",xLength,yLength,0d,0d,254d);
        createMat("D://demoTest4.png",xLength,yLength,0d,0d,0d);
    }

    private static void createMat(String fileName,int width,int height,double d1,double d2,double d3){
        Mat mat = Mat.zeros(width,height, CvType.CV_8UC3);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                mat.put(i,j,new double[]{d1,d2,d3});
            }
        }

        Imgcodecs.imwrite(fileName,mat);
    }

//    public static void main(String[] args) {
//        Mat mat = Imgcodecs.imread("D:\\demoTestInput.png");
//        int cvtype = mat.type();
//        System.out.println(String.format("cvtype: ",cvtype));
////        for (int i = 0; i <= 4; i++) {
////            for (int j = 0; j <= 5; j++) {
////                double[] content = mat.get(i,j);
////                System.out.println(String.format(" -------------- %d:%d -----------------",i,j));
////                StringBuilder sb = new StringBuilder();
////                for (int k = 0; k < content.length; k++) {
////                    sb.append(" ").append(content[k]);
////                }
////                System.out.println(sb.toString());
////                System.out.println(" -------------- end -----------------");
////            }
////        }
//
//        for (int i = 0; i <= 1000; i++) {
//            double[] content = mat.get(i,0);
//            System.out.println(String.format(" -------------- %d:%d -----------------",i,0));
//            StringBuilder sb = new StringBuilder();
//            for (int k = 0; k < content.length; k++) {
//                sb.append(" ").append(content[k]);
//            }
//            System.out.println(sb.toString());
//            System.out.println(" -------------- end -----------------");
//        }
//
//    }

    //Element[x][y] x:层数 y：栅格序号
    public static boolean transAndSaveImage(Element[][] elements,double length,double height,String filePath) throws Exception{
        if(elements == null || elements.length == 0){
            return false;
        }
        try{
            //栅格数组转图像数组（单位1米）
            List<List<Rgb>> imageRgbList = new ArrayList<>();
            for (int i = 0; i < elements.length; i++) {
                List<Rgb> rowRgbList = new ArrayList<>();
                imageRgbList.add(rowRgbList);
                for (int j = 0; j < elements[i].length; j++) {
                    Element element = elements[i][j];
                    int lengthFeature = BigDecimal.valueOf(element.getLength()).setScale(0, RoundingMode.HALF_EVEN).intValue();
                    Rgb rgb = getRgbFromLeqt(element.getLeqt());
                    for (int k = 0; k < lengthFeature; k++) {
                        rowRgbList.add(rgb);
                    }
                }
            }

            //图像数组转mat对象并做插值处理
            Mat mat = Mat.zeros(imageRgbList.get(0).size(),imageRgbList.size(), CvType.CV_8UC3);
            for (int i = 0; i < imageRgbList.size(); i++) {//层数
                List<Rgb> rowRgbList = imageRgbList.get(i);
                for (int j = 0; j < rowRgbList.size(); j++) {//栅格数
                    mat.put(j,i,rowRgbList.get(j).getVal());
                }
            }

            if(mat.empty()){
                log.info("old mat is empty");
                return true;
            }

            Mat dstResize = new Mat();
            Imgproc.resize(mat,dstResize,new Size(length * 10,height * 10),0,0,Imgproc.INTER_LINEAR);
//            Mat dstFilter2D = new Mat();
//            Mat kernel = new Mat(3,3,Imgcodecs.IMREAD_COLOR);
//            kernel.put(0,0,0,-1,0,-1,5,-1,0,-1,0);
//            Imgproc.filter2D(dstResize,dstFilter2D,-1,kernel,new Point(-1,-1),0,Core.BORDER_REPLICATE);

            Imgcodecs.imwrite(FILE_UPLOAD_PREF + filePath,dstResize);


            return true;
        }catch (Exception e){
            log.error("image trans excepiton:"+e.toString(),e);
            return false;
        }
    }

    private static RgbRange[] rangeList = new RgbRange[]{
            new RgbRange(-40,45,new Rgb(62,255,164),new Rgb(57,185,47)),//绿
            new RgbRange(45,48,new Rgb(211,254,114),new Rgb(202,175,26)),//青
            new RgbRange(48,52,new Rgb(255,203,64),new Rgb(192,146,22)),//蓝
            new RgbRange(52,56,new Rgb(87,255,234),new Rgb(1,233,239)),//黄
            new RgbRange(56,60,new Rgb(109,200,254),new Rgb(46,101,228)),//橙
            new RgbRange(60,80,new Rgb(108,119,255),new Rgb(4,4,217)),//红
            new RgbRange(80,140,new Rgb(255,123,252),new Rgb(200,0,194)) //紫
    };

    private static Rgb getRgbFromLeqt(double leqt){
        for (int i = 0; i < rangeList.length; i++) {
            if(rangeList[i].checkLeqt(leqt)){
                return rangeList[i].getRgb(leqt);
            }
        }
        return Rgb.ZERO;
    }


}